using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Forms;
using Christian.Helle.PocketNews.PocketPC.Controls;
using Christian.Helle.PocketNews.PocketPC.Data;
using Christian.Helle.PocketNews.PocketPC.NewsProtocol;
using System.Reflection;

namespace Christian.Helle.PocketNews.PocketPC
{
	public partial class frmMain : FormEx
	{
		private NntpThread worker;

		#region Delegates
		internal delegate void AddArticleHeader(ArticleHeader header);
		internal delegate void AddArticleHeaders(List<ArticleHeader> headers);
		internal delegate void UpdateStatusBar(string text);
		internal delegate void UpdateNntpStatus(bool is_working);
		internal delegate void UpdateInternetStatus(bool online);

		internal AddArticleHeader AddArticleHeaderDelegate;
		internal AddArticleHeaders AddArticleHeadersDelegate;
		internal UpdateStatusBar UpdateStatusBarDelegate;
		internal UpdateNntpStatus UpdateNntpStatusDelegate;
		internal UpdateInternetStatus UpdateInternetStatusDelegate;
		#endregion

		public frmMain()
		{
			InitializeComponent();

			#region Instantiate delegates
			UpdateStatusBarDelegate = new UpdateStatusBar(UpdateStatusMethod);
            //AddArticleHeaderDelegate = new AddArticleHeader(AddArticleHeaderMethod);
            //AddArticleHeadersDelegate = new AddArticleHeaders(AddArticleHeadersMethod);
			UpdateNntpStatusDelegate = new UpdateNntpStatus(UpdateNntpStatusMethod);
            //UpdateInternetStatusDelegate = new UpdateInternetStatus(UpdateInternetStatusMethod);
			#endregion

			LoadSubscriptions();
			Update();

			worker = new NntpThread(this);
			worker.LoadArticleHeaders();
		}

		private void LoadSubscriptions()
		{
			string[] groups = DataAccess.Instance.LoadSubscriptions();

			if (groups == null || groups.Length == 0) {
				DialogResult result = MessageBox.Show(
					"You are currently not subscribing to any newsgroups. Do you wish to subscribe to one?",
					"No Subscriptions",
					MessageBoxButtons.YesNo,
					MessageBoxIcon.Question,
					MessageBoxDefaultButton.Button1);

                if (result == DialogResult.Yes)
                {
                    using (frmNewsgroups form = new frmNewsgroups())
                    {
                        form.Owner = this;
                        if (form.ShowDialog() == DialogResult.OK)
                            groups = DataAccess.Instance.LoadSubscriptions();
                    }
				}
			}

			for (int i = 0; i < groups.Length; i++) {
				MenuItem item = new MenuItem();
				item.Text = groups[i];

				if (groups[i] == Configuration.CurrentNewsgroup) {
					item.Checked = true;
				}

				item.Click += NewsgroupItem_Click;
				menuNewsgroups.MenuItems.Add(item);
			}
		}

		void NewsgroupItem_Click(object sender, EventArgs e)
		{
			var item = (MenuItem)sender;

			for (int i = 0; i < menuNewsgroups.MenuItems.Count; i++) {
				if (menuNewsgroups.MenuItems[i].Text == item.Text) {
					menuNewsgroups.MenuItems[i].Checked = true;
				} else {
					menuNewsgroups.MenuItems[i].Checked = false;
				}
			}

			Configuration.CurrentNewsgroup = item.Text;
			Configuration.SaveChanges();

			worker.LoadArticleHeaders();
		}

		private void Exit_Click(object sender, EventArgs e)
		{
			if (Configuration.CompressDb) {
				UpdateStatusMethod("Compressing local storage");

				var sqlce = new DatabaseEngine();
				sqlce.CompactDatabase();
			}

			UpdateStatusMethod("Exiting...");

			Application.Exit();
		}

		private void Settings_Click(object sender, EventArgs e)
		{
            using (frmSettings form = new frmSettings()) {
                form.Owner = this;
                form.ShowDialog();
            }            
		}

		private void menuRefresh_Click(object sender, EventArgs e)
		{
			worker.LoadArticleHeaders();
		}

		private void SubscribeToNewsgroup_Click(object sender, EventArgs e)
        {
            using (frmNewsgroups form = new frmNewsgroups()) {
                form.Owner = this;
                form.ShowDialog();
            }

			ReloadNewsgroupMenu();
			worker.LoadArticleHeaders();
		}

		private void ReloadNewsgroupMenu()
		{
			menuNewsgroups.MenuItems.Clear();
			menuNewsgroups.MenuItems.Add(menuSubscribe);
			menuNewsgroups.MenuItems.Add(menuUnsubscribe);
			menuNewsgroups.MenuItems.Add(menuSeparator);

			LoadSubscriptions();
		}

		private void menuRead_Click(object sender, EventArgs e)
		{
			if (menuRead.Text == "Read") {
				ViewArticle();
			} else {
				worker.Abort();
			}
		}

		private void ViewArticle()
		{
			UpdateStatusMethod("Retrieving article body");

			ArticleHeader header = lvArticles.SelectedItem as ArticleHeader;
			if (header != null) {
				string body = null;
				int msg_id = int.Parse(header.ID);

				using (new WaitCursor()) {
					body = DataAccess.Instance.GetArticleBody(
						Configuration.CurrentNewsgroup,
						msg_id);

					if (string.IsNullOrEmpty(body)) {
						using (Nntp nntp = new Nntp()) {
							nntp.Connect(Configuration.NntpServer);
							if (nntp.IsConnected) {
								nntp.SelectGroup(Configuration.CurrentNewsgroup);
								body = nntp.DownloadArticleBody(header.ID);
							}
						}

						if (!string.IsNullOrEmpty(body)) {
							DataAccess.Instance.SaveArticleBody(
								Configuration.CurrentNewsgroup,
								msg_id,
								body);
						}
					}
				}

				if (string.IsNullOrEmpty(body)) {
					UpdateStatusMethod("Unable to retrieve body");
					return;
				}

                using (frmMessage read = new frmMessage(header, body, lvArticles.SelectedIndex)) {
                    read.Owner = this;
                    read.ShowDialog();
                }

				UpdateStatusMethod(
					string.Format(
						"{0} Posts",
						Cache.ArticleCollection.Count));
			}
		}

		private void UpdateStatusMethod(string text)
		{
			sbStatus.Text = text;
			sbStatus.Update();
		}

        //private void AddArticleHeadersMethod(List<ArticleHeader> headers)
        //{
        //    //lvArticles.Items.InsertRange(0, headers);
        //}

        //private void AddArticleHeaderMethod(ArticleHeader header)
        //{
        //    //lvArticles.Items.Insert(0, header);
        //}

		private void UpdateNntpStatusMethod(bool is_working)
		{
			if (is_working) {
				menuRead.Text = "Cancel";
			} else {
				menuRead.Text = "Read";

				UpdateStatusMethod(
					string.Format(
						"{0} Posts",
						Cache.ArticleCollection.Count));
			}
		}

		internal void StartArticleDownloadDelegate(object sender, EventArgs e)
		{
			lvArticles.BeginUpdate();
			lvArticles.Items.Clear();
		}

		internal void EndArticleDownloadDelegate(object sender, EventArgs e)
		{
			lvArticles.Items.AddRange(Cache.ArticleCollection);
			lvArticles.EndUpdate();

			if (Cache.NewArticles.Count == 1) {
				NotificationBalloon.Show(
					"New Post",
					"There is a new post in the newsgroup");
			} else if (Cache.NewArticles.Count > 1) {
				NotificationBalloon.Show(
					"New Posts",
					string.Format(
						"There are {0} new posts in the newsgroup",
						Cache.NewArticles.Count));
			}
		}

        //private void UpdateInternetStatusMethod(bool online)
        //{
        //}

		private void menuNew_Click(object sender, EventArgs e)
		{
            using (frmCompose create = new frmCompose()) {
                create.Owner = this;
                create.ShowDialog();
            }
		}

		private void menuReply_Click(object sender, EventArgs e)
		{
			ReplyToPost();
		}

        //private string GetArticleBody(ArticleHeader header, bool save_body)
        //{
        //    string body = null;

        //    UpdateStatusMethod("Retrieving article body");

        //    if (header != null) {
        //        int msg_id = int.Parse(header.ID);

        //        using (new WaitCursor()) {
        //            body = DataAccess.Instance.GetArticleBody(
        //                Configuration.CurrentNewsgroup,
        //                msg_id);

        //            if (string.IsNullOrEmpty(body)) {
        //                using (Nntp nntp = new Nntp()) {
        //                    nntp.Connect(Configuration.NntpServer);
        //                    if (nntp.IsConnected) {
        //                        nntp.SelectGroup(Configuration.CurrentNewsgroup);
        //                        body = nntp.DownloadArticleBody(header.ID);
        //                    }
        //                }

        //                if (save_body) {
        //                    if (!string.IsNullOrEmpty(body)) {
        //                        DataAccess.Instance.SaveArticleBody(
        //                            Configuration.CurrentNewsgroup,
        //                            msg_id,
        //                            body);
        //                    }
        //                }
        //            }
        //        }

        //        if (string.IsNullOrEmpty(body)) {
        //            UpdateStatusMethod("Unable to retrieve body");
        //        }
        //    }

        //    return body;
        //}

		private void ReplyToPost()
		{
			UpdateStatusMethod("Retrieving article body");

			ArticleHeader header = lvArticles.SelectedItem as ArticleHeader;
			if (header != null) {
				string body = null;
				int msg_id = int.Parse(header.ID);

				using (new WaitCursor()) {
					body = DataAccess.Instance.GetArticleBody(
						Configuration.CurrentNewsgroup,
						msg_id);

					if (string.IsNullOrEmpty(body)) {
						using (Nntp nntp = new Nntp()) {
							nntp.Connect(Configuration.NntpServer);
							if (nntp.IsConnected) {
								nntp.SelectGroup(Configuration.CurrentNewsgroup);
								body = nntp.DownloadArticleBody(header.ID);
							}
						}

						if (!string.IsNullOrEmpty(body)) {
							DataAccess.Instance.SaveArticleBody(
								Configuration.CurrentNewsgroup,
								msg_id,
								body);
						}
					}
				}

				if (string.IsNullOrEmpty(body)) {
					UpdateStatusMethod("Unable to retrieve body");
					return;
				}

                using (frmCompose reply = new frmCompose(Configuration.CurrentNewsgroup,header.Subject,body)) {
                    reply.Owner = this;
                    reply.ShowDialog();
                }

			    UpdateStatusMethod(
					string.Format(
						"{0} Posts",
						Cache.ArticleCollection.Count));
			}
		}

		private void timer_Tick(object sender, EventArgs e)
		{
			worker.LoadArticleHeaders();
		}

		private void frmMain_Closing(object sender, CancelEventArgs e)
		{
			NotificationBalloon.Kill();
		}

		private void menuDrafts_Click(object sender, EventArgs e)
		{
			Cache.Drafts = DataAccess.Instance.LoadDrafts();

            using (frmDrafts drafts = new frmDrafts()) {
                drafts.Owner = this;
                drafts.ShowDialog();
            }
		}

		private void menuAbout_Click(object sender, EventArgs e)
		{
			string version = Assembly.GetExecutingAssembly().GetName().Version.ToString();
			MessageBox.Show(
				"Windows Mobile Edition\n" + "Version: " + version + "\n\nWritten By:\nChristian Resma Helle",
				"Pocket News",
				MessageBoxButtons.OK,
				MessageBoxIcon.Asterisk,
				MessageBoxDefaultButton.Button1);
		}
	}
}